package repository

import (
	"blog_go/internal/model"
	"errors"
	"time"
)

type TagRepository interface {
	QueryTag(categoryId int) ([]*model.Tag, error)
	QueryAllTag() ([]*model.TagView, error)
	AddTag(tag model.TagView) error
	UpdateTag(tag model.TagView) error
	DelTag(tagId int) error
}

type tagRepository struct {
	*BaseRepository
}

func NewTagRepository(repository *BaseRepository) TagRepository {
	return &tagRepository{
		BaseRepository: repository,
	}
}

// 查询标签
func (r *tagRepository) QueryTag(categoryId int) ([]*model.Tag, error) {
	tags := make([]*model.Tag, 0)

	query := `
		SELECT DISTINCT 
			act.tag_id, 
			t.tag_name, 
			t.update_time 
		FROM 
			article_category_tag act
		LEFT JOIN 
			tag t 
		ON act.tag_id = t.tag_id`

	var queryParams []interface{}

	if categoryId != 0 {
		query += " WHERE act.category_id = ?"
		queryParams = append(queryParams, categoryId)
	}

	rows, err := r.db.Query(query, queryParams...)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var tag model.Tag

		err := rows.Scan(&tag.TagId, &tag.TagName, &tag.UpdateTime)
		if err != nil {
			return nil, err
		}

		tags = append(tags, &tag)
	}

	return tags, nil
}

// 查询标签及所属分类
func (r *tagRepository) QueryAllTag() ([]*model.TagView, error) {
	tags := make([]*model.TagView, 0)

	query := `
		SELECT 
			act.tag_id, 
			t.tag_name, 
			t.update_time, 
			ac.category_name, 
			ac.category_id 
		FROM 
			article_category_tag act
		LEFT JOIN 
			tag t 
		ON act.tag_id = t.tag_id
		LEFT JOIN 
			article_category ac 
		on ac.category_id = act.category_id`

	rows, err := r.db.Query(query)

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	//用map存储
	tagsMap := make(map[int]*model.TagView)

	for rows.Next() {
		var tag model.Tag

		err := rows.Scan(&tag.TagId, &tag.TagName, &tag.UpdateTime, &tag.CategoryName, &tag.CategoryId)
		if err != nil {
			return nil, err
		}

		tagValue, exists := tagsMap[tag.TagId]

		//不存在就初始化
		if !exists {
			tagValue = &model.TagView{
				TagId:        tag.TagId,
				TagName:      tag.TagName,
				UpdateTime:   tag.UpdateTime,
				CategoryId:   []int{},
				CategoryName: []string{},
			}

			tagsMap[tag.TagId] = tagValue
		}

		//添加到对应的切片中
		tagValue.CategoryId = append(tagValue.CategoryId, tag.CategoryId)
		tagValue.CategoryName = append(tagValue.CategoryName, tag.CategoryName)
	}

	for _, value := range tagsMap {
		tags = append(tags, value)
	}

	return tags, nil
}

// 添加标签
func (r *tagRepository) AddTag(tag model.TagView) error {
	//标签名不能重复
	var count int

	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	err = tx.QueryRow(`
		SELECT 
			count(*) 
		FROM 
			tag 
		WHERE 
			tag_name = ?`, tag.TagName).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("标签名重复")
	}

	createTime := time.Now().Format("2006-01-02 15:04:05")
	ret, err := tx.Exec(`
		INSERT INTO tag
		(
			tag_name, 
			update_time
		) 
		VALUES (?, ?)`, tag.TagName, createTime)
	if err != nil {
		return err
	}

	tagId, err := ret.LastInsertId()
	if err != nil {
		return err
	}

	if len(tag.CategoryId) > 0 {
		// 使用准备语句
		stmt, err := tx.Prepare(`
			INSERT INTO article_category_tag 
			(
				tag_id, 
				category_id
			) 
			VALUES (?, ?)`)
		if err != nil {
			return err
		}

		defer stmt.Close()

		for _, categoryId := range tag.CategoryId {
			_, err = stmt.Exec(tagId, categoryId)
			if err != nil {
				return err
			}
		}
	}

	err = tx.Commit()
	return err
}

// 更新标签
func (r *tagRepository) UpdateTag(tag model.TagView) error {
	// 标签名不能重复
	var count int

	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	err = tx.QueryRow(`
		SELECT 
			count(*) 
		FROM 
			tag 
		WHERE 
			tag_name = ? 
			AND tag_id != ?`, tag.TagName, tag.TagId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("标签名重复")
	}

	//更新tag表
	updateTime := time.Now().Format("2006-01-02 15:04:05")
	_, err = tx.Exec(`
		UPDATE 
			tag 
		SET 
			tag_name = ?, 
			update_time = ?
		WHERE 
			tag_id = ? `, tag.TagName, updateTime, tag.TagId)
	if err != nil {
		return err
	}

	//先删除再增加
	_, err = tx.Exec(`
		DELETE FROM article_category_tag 
		WHERE tag_id = ?`, tag.TagId)
	if err != nil {
		return err
	}

	if len(tag.CategoryId) > 0 {
		// 使用准备语句
		stmt, err := tx.Prepare(`
			INSERT INTO article_category_tag 
			(
				tag_id, 
				category_id
			) 
			VALUES (?, ?)`)
		if err != nil {
			return err
		}

		defer stmt.Close()

		for _, categoryId := range tag.CategoryId {
			_, err = stmt.Exec(tag.TagId, categoryId)
			if err != nil {
				return err
			}
		}
	}

	err = tx.Commit()
	return err
}

// 删除标签
func (r *tagRepository) DelTag(tagId int) error {
	//当前标签没有文章引用该标签可以删除
	var count int

	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			article_tag 
		WHERE 
			tag_id = ?`, tagId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("该标签已被文章引用")
	}

	//删除标签
	_, err = tx.Exec(`
		DELETE FROM tag 
		WHERE tag_id = ?`, tagId)
	if err != nil {
		return err
	}

	//删除分类标签关系
	_, err = tx.Exec(`
		DELETE FROM article_category_tag 
		WHERE tag_id = ?`, tagId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}
